import store from "../../../store";
import request from './request.js';
/************公共工具方法************/
let globalObj = {
	//生成随机数
	uuid() {
		let len = 8; //长度
		let radix = 8; //基数
		let chars = 'GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
		let uuid = [],
			i;
		radix = radix || chars.length;
		if (len) {
			for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
		} else {
			let r = null;
			uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
			uuid[14] = '4';
			for (i = 0; i < 36; i++) {
				if (!uuid[i]) {
					r = 0 | (Math.random() * 16);
					uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
				}
			}
		}
		return uuid.join('');
	},

	//计算文件的大小
	diskSize: (num) => {
		if (!num) return '0B';
		let k = 1024; //设定基础容量大小
		let sizeStr = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; //容量单位
		let i = 0; //单位下标和次幂
		for (let l = 0; l < 8; l++) { //因为只有8个单位所以循环八次
			if (num / Math.pow(k, l) < 1) { //判断传入数值 除以 基础大小的次幂 是否小于1，这里小于1 就代表已经当前下标的单位已经不合适了所以跳出循环
				break; //小于1跳出循环
			}
			i = l; //不小于1的话这个单位就合适或者还要大于这个单位 接着循环
		}
		//例： 900 / Math.pow(1024, 0)  1024的0 次幂 是1 所以只要输入的不小于1 这个最小单位就成立了；
		//   900 / Math.pow(1024, 1)  1024的1次幂 是1024  900/1024 < 1 所以跳出循环 下边的 i = l；就不会执行  所以 i = 0； sizeStr[0] = 'B';
		//   以此类推 直到循环结束 或 条件成立
		return (num / Math.pow(k, i)).toFixed(2) + sizeStr[i]; //循环结束 或 条件成立 返回字符
	},

	//计算网速
	filterNet: (size) => {
		let filterSize = ''
		if (size < 1024) {
			filterSize = size.toFixed(2) + 'B';
		} else if (size / 1024 >= 1 && size / 1024 / 1024 < 1) {
			filterSize = (Math.floor(size / 1024 * 100) / 100).toFixed(2) + 'KB';
		} else if (size / 1024 / 1024 >= 1) {
			filterSize = (Math.floor(size / 1024 / 1024 * 100) / 100).toFixed(2) + 'M';
		}
		return filterSize + '/s'
	}
}
/************重要的接口************/
// 获取上传时候需要的token
async function getToken(task) {
	const params = {
		method: 'POST',
		url: '/nas/user/upload/userInfo',
		contentType: 'application/x-www-form-urlencoded',
		data: {
			pathFileName: task.fileInfo.catalogue + task.fileInfo.name,
			uploadType: 0
		}
	};
	// console.log(params, '获取token的请求头')
	const res = await request(params);
	console.log(res, '返回的token')
	task.token = res.data
	task.startSliceUpload()
}
// 小文件上传
async function getMiniToken(task) {
	const params = {
		method: 'POST',
		url: '/nas/user/upload/userInfo',
		contentType: 'application/x-www-form-urlencoded',
		data: {
			pathFileName: task.fileInfo.catalogue + task.fileInfo.name,
			uploadType: 0
		}
	};
	console.log(params, '获取token的请求头')
	const res = await request(params);
	console.log(res, '返回的token')
	task.token = res.data
	task.smallfileUpload()
}

// 判断是否存在这个文件，如果存在则修改名字
async function finalDeal(task) {
	const params = {
		method: 'POST',
		url: '/nas/rd_center/data/get',
		data: {
			method: 'capacity.nas.cloud.file.exist',
			type: 1,
			data: {
				directory: task.fileInfo.catalogue,
				filename: task.fileInfo.name + '.crash'
			}
		}
	};
	// console.log(params, '判断是否存在的请求头');
	const res = await request(params);
	// console.log(res, '判断是否存在的返回结果');
	if (res.data) {
		// 改变文件的名称
		const requestInfo = {
			method: 'POST',
			url: '/nas/rd_center/data/get',
			data: {
				method: 'capacity.nas.cloud.file.rename',
				type: 1,
				data: {
					directory: task.fileInfo.catalogue,
					filename: task.fileInfo.name + '.crash',
					newFilename: task.fileInfo.name
				}
			}
		};
		request(requestInfo);
	} else {}
	// console.log(res, '查询文件是否存在')
}

let totalSliceList = [] //所有待切片的文件列表
let isSlicing = false //是否正在切片

/************文件切片公共方法************/
function fileSlice() {
	//切片列表为空或者切片任务未结束正在进行中则不进行切片
	if (!totalSliceList || !totalSliceList.length || isSlicing) return;
	//更新切片状态为正在进行
	isSlicing = true;
	//取出一个文件，进行切片
	let task = totalSliceList.pop()
	//原生切片插件
	let KJFileSlice = uni.requireNativePlugin('KJ-FileSlice');
	//文件开始切片，将本地URL路径转换成平台绝对路径，保存切片地址，一定要是_doc目录
	if (task.tempFilePath.indexOf("_doc") != -1) {
		task.tempFilePath = plus.io.convertLocalFileSystemURL(task.tempFilePath);
	} else {
		task.tempFilePath = task.tempFilePath.replace("file://", "");
	}
	//切片保存的文件夹路径
	let savePath = '_doc/' + task.sliceFileName;
	savePath = plus.io.convertLocalFileSystemURL(savePath);
	let dic = {
		"pathFileName": task.tempFilePath, //上传文件的临时地址
		"savePath": savePath, //保存切片地址，一定要是_doc目录
		"sliceSize": task.fixedSliceSize, //切片大小，单位（B）
		"sliceSuffixName": "" //保存切片的后缀名
	}
	//原生插件调用 开始切片
	KJFileSlice.start(dic, (sliceRes) => {
		//记录文件总的切片信息
		task.fileInfo.slices = sliceRes.slices;
		//记录文件总的切片数
		task.totalPieces = sliceRes.slices.length
		//切片完成，更新切片状态为结束
		isSlicing = false;
		//先获取token后上传文件
		getToken(task)
		//继续进行下一个切片任务
		fileSlice();
	}, function(e) {
		//console.log('读取分片存储目录失败：' + e.message)
	});
}

/************删除切片************/
function deleteSliceData(task) {
	//无切片信息直接返回
	if (!task.fileInfo.slices || !task.fileInfo.slices.length) return;
	let savePath = '_doc/' + task.sliceFileName;
	savePath = plus.io.convertLocalFileSystemURL(savePath);
	// console.log('删除分片路径', savePath);
	plus.io.resolveLocalFileSystemURL(savePath, function(entry) {
		//读取这个目录对象
		var directoryReader = entry.createReader();
		//读取这个目录下的所有文件
		directoryReader.readEntries(function(entries) {
			//如果有才操作
			if (entries.length > 0) {
				//删除目录将会删除其下的所有文件及子目录 不能删除根目录，如果操作删除根目录
				//将会删除目录下的文件及子目录，不会删除根目录自身。 删除目录成功通过succesCB
				//回调返回，失败则通过errorCB返回。
				entry.removeRecursively(function(entry) {
					task.sliceIndex = 0
					task.totalPieces = 0
					task.fileInfo.slices = []
				}, function(e) {})
			}
		}, function(e) {
			//console.log('读取文件失败：' + e.message)
		})
	}, function(e) {
		//console.log('读取目录失败：' + e.message)
	})
}

/************文件上传处理类************/
let nasUploadClass = class {
	constructor(options) {
		let len = options.filePath.length;
		let index = options.filePath.lastIndexOf('/');
		this.fileInfo = {
			...options,
			name: options.filePath.substring(index + 1, len)
		} //文件的原始信息
		this.options = options // 传递的参数
		this.uid = options.uid //唯一的标识
		this.tempFilePath = options.filePath //上传文件的本地地址
		this.uploadTask = null //单个切片上传的进度对象
		this.taskStatus = 'pending' //任务状态 等待、开始、暂停、失败 默认为等待pending
		this.fixedSliceSize = 1024 * 1024 * 4 //固定每次切片的大小 （暂定4M）
		this.totalPieces = 0 //文件总的切片数
		this.sliceIndex = 0 //当前的分片序号 默认值（0开始）
		this.retryCount = 3 //重复上传最多3次
		this.partSize = '0B' // 已经上传的大小
		this.speed = 0 // 上传的进度
		this.sliceFileName = this.fileInfo.name + '_' + globalObj.uuid() //切片存放的文件夹名称
		this.totalSize = globalObj.diskSize(this.fileInfo.size) // 文件的总大小
	}
	/************取消上传************/
	cancelUpload() {
		this.uploadTask && this.uploadTask.abort()
		deleteSliceData(this)
		this.pauseUpload()
	}
	/************暂停上传************/
	pauseUpload() {
		this.downloadNet = '0B/s'
		this.taskStatus = 'pause';
	}
	/************开始切片************/
	startUpload() {
		this.taskStatus = 'start';
		// if (plus.os.name == "Android") {
		// 	let fileSize = this.fileInfo.size;
		// 	if (fileSize > this.fixedSliceSize) {
		// 		totalSliceList.push(this)
		// 		fileSlice();
		// 	} else {
		// 		//小文件无需切片,先获取token后上传文件
		// 		getMiniToken(this)
		// 	}
		// } else {
		totalSliceList.push(this)
		fileSlice();
		// }
		//切片完成后将上传的实例对象更新到store中
		// store.dispatch('NASUPLOADINGLIST_ADD', this)
	}
	/************文件分片上传************/
	startSliceUpload() {
		//暂停状态终止上传
		if (this.taskStatus == 'pause') return false
		if (!this.fileInfo.slices.length) {
			//没有分片上传下一个文件
			this.cancelUpload()
			this.taskStatus = 'fail';
			store.commit('nasUploadingListDelete', this);
			return
		}
		//请求参数
		this.params = {
			fileName: this.fileInfo.size < this.fixedSliceSize ? this.fileInfo.name : this.fileInfo.name +
				'.crash', //上传的文件名称
			totalSlice: this.totalPieces, //总分片数
			currentSlice: this.sliceIndex + 1, //当前的分片数
			offset: this.fileInfo.size < this.fixedSliceSize ? 0 : this.sliceIndex * this
				.fixedSliceSize, //已经上传的文件大小
			directory: this.fileInfo.catalogue //要上传的文件目录
		}
		console.log('请求的参数~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~', this.params)
		//不采用原生assign 有兼容性问题
		// if (this.customParams) this.assignParams(this.reqParams, this.customParams)
		//如果没有值就删除
		this.isError = false
		let filePath = plus.io.convertAbsoluteFileSystem(this.fileInfo.slices[
			this.sliceIndex].filePath) ? plus.io.convertAbsoluteFileSystem(this.fileInfo.slices[
			this.sliceIndex].filePath) : 0
		console.log({
			url: 'http://58.34.36.138:18480/nasforward/file/upload?uploadToken=' + this.token,
			filePath: filePath,
			formData: this.params,
			name: 'content',
			size: this.fileInfo.size
		}, '上传的参数')
		this.uploadTask = uni.uploadFile({
			url: 'http://58.34.36.138:18480/nasforward/file/upload?uploadToken=' + this.token,
			filePath: filePath,
			formData: this.params,
			name: 'content',
			success: (res) => {
				// console.log('分片上传的结果', res)
				if (res.statusCode === 200) {
					let severData = JSON.parse(res.data)
					// console.log('分片上传成功', severData)
					if (severData.code == 200) {
						// console.log(this.sliceIndex, 'this.sliceIndex')
						// console.log(this.totalPieces, 'this.totalPieces')
						// 计算已经上传的大小
						if (this.sliceIndex < this.totalPieces - 1) {
							if (this.fileInfo.size < this.fixedSliceSize) {
								this.partSize = globalObj.diskSize(this.fileInfo.size)
							} else {
								this.partSize = globalObj.diskSize((this.sliceIndex + 1) * this
									.fixedSliceSize);
							}
							console.log(this.partSize, 'this.partSize')
						} else {
							this.partSize = globalObj.diskSize(this.fileInfo.size);
						}
						// 计算进度
						this.speed = Math.floor(((this.sliceIndex + 1) / this.totalPieces) *
							100);
						//最后一片上传完成
						if (this.sliceIndex >= this
							.totalPieces - 1) {
							//先查询那个文件是否存在，然后重命名那个已经上传的文件
							if (this.sliceIndex > 0) {
								// console.log('上传完成了')
								finalDeal(this)
							}
							//删除分片 
							deleteSliceData(this);
							store.commit('nasUploadingListDelete', this);
							// setTimeout(() => {
							//   if (this.options.success) this.options.success(
							//     res)
							// }, 500)
						} else {
							// 继续下一个分片上传
							this.sliceIndex++
							this.startSliceUpload()
						}
					} else if (severData.code == '2') {
						//console.log('重复上传', res)
						//备份重复
						this.taskStatus = 'fail';
						// store.commit('deletePABackupTask', this);
						// setTimeout(() => {
						//   if (this.options.success) this.options.success(
						//     res)
						// }, 500)
					} else {
						//上传失败回调
						this.retryCount ? --this.retryCount : '';
						if (this.retryCount <= 0) {
							this.cancelUpload()
							this.taskStatus = 'fail';
							this.isError = true
							this.errorMessage = severData.message;
							// store.commit('nasUploadingListDelete', this);

						} else {
							setTimeout(() => {
								this.sliceIndex = 0;
								this.startSliceUpload()
							}, 3000)
						}
					}
				}
			},
			fail: (err) => {
				//console.log('文件上传请求失败', err, this);
				this.retryCount ? --this.retryCount : '';
				if (this.retryCount <= 0) {
					this.cancelUpload()
					this.taskStatus = 'fail';
					this.isError = true;
					store.commit('nasUploadingListDelete', this);
					setTimeout(() => {
						if (this.options.error) this.options.error(err)
					}, 500)

				} else {
					setTimeout(() => {
						this.sliceIndex = 0;
						this.startSliceUpload()
					}, 3000)
				}
			},
		})
	}
	// 小文件上传
	smallfileUpload() {
		if (this.taskStatus == 'pause') return false
		plus.io.resolveLocalFileSystemURL(plus.io.convertAbsoluteFileSystem(this.tempFilePath), (entry) => {
			entry.file((file) => {
				console.log(file, 'file')
				//请求参数
				this.params = {
					fileName: file.name, //上传的文件名称
					totalSlice: 1, //总分片数
					currentSlice: 1, //当前的分片数
					offset: 0, //已经上传的文件大小
					directory: this.fileInfo.catalogue //要上传的文件目录
				}
				console.log(params, 'params')
				this.isError = false
				this.uploadTask = uni.uploadFile({
					url: 'http://58.34.36.138:18480/nasforward/file/upload?uploadToken=' +
						this.token,
					formData: this.params,
					filePath: plus.io.convertAbsoluteFileSystem(this.tempFilePath) ?
						plus.io.convertAbsoluteFileSystem(this.tempFilePath) : 0,
					name: 'content',
					success: (res) => {
						if (res.statusCode === 200) {
							let severData = JSON.parse(res.data)
							// console.log('分片上传成功', severData)
							if (severData.code == 200) {
								// if (severData.fid) {
								if (this.sliceIndex < this.totalPieces) {
									if (this.fileInfo.size < this.fixedSliceSize) {
										this.partSize = globalObj.diskSize(this
											.fileInfo.size)
									} else {
										this.partSize = globalObj.diskSize((this
												.sliceIndex + 1) * this
											.fixedSliceSize);
									}
									console.log(this.partSize, 'this.partSize')
								} else {
									this.partSize = globalObj.diskSize(this.fileInfo
										.size);
								}
								// 计算进度
								this.speed = Math.floor(((this.sliceIndex + 1) /
										this.totalPieces) *
									100);
								console.log('文件上传成功', severData)
								store.commit('nasUploadingListDelete', this);
								// setTimeout(() => {
								// 	if (this.options.success) this.options
								// 		.success(
								// 			res)
								// }, 500)
								// }
							} else if (severData.code == '2') {
								// console.log('重复上传', res)
								// 备份重复
								this.taskStatus = 'fail';
								store.commit('nasUploadingListDelete', this);
								// setTimeout(() => {
								// 	if (this.options.success) this.options
								// 		.success(
								// 			res)
								// }, 500)
							} else {
								// 上传失败回调
								// console.log('上传失败', res);
								this.retryCount ? --this.retryCount : '';
								if (this.retryCount <= 0) {
									this.cancelUpload()
									this.taskStatus = 'fail';
									this.isError = true
									this.errorMessage = severData.message;
									store.commit('nasUploadingListDelete', this);
									// setTimeout(() => {
									// 	if (this.options.error) this.options
									// 		.error(res)
									// }, 500)
								} else {
									setTimeout(() => {
										this.sliceIdx = 0;
										this.uploadFileSize = 0;
										this.smallfileUpload()
									}, 3000)
								}
							}
						}
					},
					fail: (err) => {
						// console.log('文件上传请求失败', err, this);
						this.retryCount ? --this.retryCount : '';
						if (this.retryCount <= 0) {
							this.cancelUpload()
							this.taskStatus = 'fail';
							this.isError = true;
							store.commit('deletePABackupTask', this);
							setTimeout(() => {
								if (this.options.error) this.options.error(
									err)
							}, 500)
						} else {
							setTimeout(() => {
								this.sliceIdx = 0;
								this.uploadFileSize = 0;
								this.smallfileUpload()
							}, 3000)
						}
					}
				})
			})
		})
	}
}
export default {
	nasUploadClass
}
